package fr.afcepf.ai89.esharing.data;

import java.util.Date;
import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.hibernate.validator.util.privilegedactions.GetAnnotationParameter;

import fr.afcepf.ai89.esharing.entity.Aem;
import fr.afcepf.ai89.esharing.entity.Avis;
import fr.afcepf.ai89.esharing.entity.Emprunt;
import fr.afcepf.ai89.esharing.entity.MessagePrive;
import fr.afcepf.ai89.esharing.entity.Proprietaire;

@Stateless
public class DAOEmprunt implements IDAOEmprunt {

	@PersistenceContext(unitName = "ESharingPhase22")
	EntityManager em;

	@Override
	public Emprunt getEmprunt(int idEmprunt) {
		
		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " +
				   "WHERE e.idEmprunt = :pmp");

		hql.setParameter("pmp", idEmprunt);
		Emprunt emp = (Emprunt) hql.getSingleResult();

		return emp;

	}

	@Override
	public List<Emprunt> getEmprunts() {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
								   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
								   "LEFT JOIN FETCH e.avisSurPreteur " + 
								   "INNER JOIN FETCH e.aem " + 
								   "INNER JOIN FETCH e.proprietaire " +
								   "LEFT JOIN FETCH e.motivationAnnulation " + 
								   "LEFT JOIN FETCH e.motivationRefus");
		
		List<Emprunt> emps = (List<Emprunt>)hql.getResultList();
		
		return emps;

	}

	@Override
	public List<Emprunt> getEmprunts(Proprietaire prop) {
		
		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.proprietaire.idUtilisateur = :pmp");

		hql.setParameter("pmp", prop.getIdUtilisateur());
		List<Emprunt> emps = (List<Emprunt>)hql.getResultList();
		
		return emps;

	}

	@Override
	public List<Emprunt> getEmprunts(Aem aem) {
		
		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.aem.idAem = :pmp");

		hql.setParameter("pmp", aem.getIdAem());
		List<Emprunt> emps = (List<Emprunt>)hql.getResultList();
		
		return emps;
		
	}

	@Override
	public List<Emprunt> getEmprunts(Date debut, Date fin) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus" + 
				   "WHERE e.dateDebut >= :param1 " + 
				   "AND ((e.dateFin <= :param2 AND e.dateRestitution IS NULL) OR dateRestitution <= :param2)");

		hql.setParameter("param1", debut);
		hql.setParameter("param2", fin);
		List<Emprunt> emps = (List<Emprunt>)hql.getResultList();
		
		return emps;
		
	}

	@Override
	public List<Emprunt> getEmpruntsPasses(Proprietaire prop) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.proprietaire.idUtilisateur = :pmp1 " + 
				   "AND e.dateValidation IS NOT NULL " + 
				   "AND e.dateRestitution IS NOT NULL " + 
				   "AND e.dateRestitution < CURRENT_DATE " + 
				   "AND e.dateAnnulation IS NULL");

		hql.setParameter("pmp1", prop.getIdUtilisateur());
		List<Emprunt> emps = (List<Emprunt>)hql.getResultList();
		
		return emps;

	}

	@Override
	public List<Emprunt> getEmpruntsEnCours(Proprietaire prop) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.proprietaire.idUtilisateur = :pmp1 " + 
				   "AND e.dateValidation IS NOT NULL " + 
				   "AND e.dateDebut < CURRENT_DATE " + 
				   "AND e.dateRestitution IS NULL " + 
				   "AND e.dateAnnulation IS NULL");

		hql.setParameter("pmp1", prop.getIdUtilisateur());
		List<Emprunt> emps = (List<Emprunt>)hql.getResultList();
		
		return emps;

	}

	@Override
	public List<Emprunt> getEmpruntsPlannifies(Proprietaire prop) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.proprietaire.idUtilisateur = :pmp1 " + 
				   "AND e.dateValidation IS NOT NULL " + 
				   "AND e.dateDebut > CURRENT_DATE " + 
				   "AND e.dateAnnulation IS NULL");

		hql.setParameter("pmp1", prop.getIdUtilisateur());
		List<Emprunt> emps = (List<Emprunt>)hql.getResultList();
		
		return emps;

	}

	@Override
	public List<Emprunt> getEmpruntsNonValides(Proprietaire prop) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.proprietaire.idUtilisateur = :pmp " + 
				   "AND e.dateValidation IS NULL " + 
				   "AND e.dateRefus IS NULL " + 
				   "AND e.dateAnnulation IS NULL");

		hql.setParameter("pmp", prop.getIdUtilisateur());
		List<Emprunt> emps = (List<Emprunt>)hql.getResultList();
		
		return emps;

	}

	@Override
	public int demanderEmprunt(Emprunt emprunt) {
		
		emprunt.setDateDemande(new Date());
		em.persist(emprunt);
		
		Query hql = em.createQuery("SELECT MAX(idEmprunt) FROM Emprunt e");
		int idEmprunt = (Integer)hql.getSingleResult();
		
		return idEmprunt;
		
	}

	@Override
	public int validerEmprunt(Emprunt emprunt) {

		emprunt = (Emprunt)em.find(Emprunt.class, emprunt.getIdEmprunt());
		emprunt.setDateValidation(new Date());
		
		em.merge(emprunt);
		return emprunt.getIdEmprunt();

	}

	@Override
	public int refuserEmprunt(Emprunt emprunt) {

		emprunt = (Emprunt)em.find(Emprunt.class, emprunt.getIdEmprunt());
		emprunt.setDateRefus(new Date());
		
		em.merge(emprunt);
		return emprunt.getIdEmprunt();

	}

	@Override
	public int majEmprunt(Emprunt emprunt) {

		Emprunt empruntBDD = (Emprunt)em.find(Emprunt.class, emprunt.getIdEmprunt());
		
		empruntBDD.setDateDebut(emprunt.getDateDebut());
		empruntBDD.setDateFin(emprunt.getDateFin());
		
		em.persist(empruntBDD);
		return emprunt.getIdEmprunt();

	}

	@Override
	public int annulerEmprunt(Emprunt emprunt) {

		emprunt = (Emprunt)em.find(Emprunt.class, emprunt.getIdEmprunt());
		emprunt.setDateAnnulation(new Date());
		
		em.merge(emprunt);
		return emprunt.getIdEmprunt();

	}

	@Override
	public int marquerAemRendu(Emprunt emprunt) {
		
		emprunt=(Emprunt)em.find(Emprunt.class, emprunt.getIdEmprunt());
		emprunt.setDateRestitution(new Date());
		
		em.persist(emprunt);
		return emprunt.getIdEmprunt();

	}

	@Override
	public int laisserAvisSurPreteur(Emprunt emprunt) {
		
		Emprunt emp = (Emprunt)em.find(Emprunt.class, emprunt.getIdEmprunt());
		emp.setAvisSurPreteur(emprunt.getAvisSurPreteur());
		
		em.merge(emprunt);
		return emprunt.getIdEmprunt();

	}

	@Override
	public int laisserAvisSurEmprunteur(Emprunt emprunt) {
		
		Emprunt emp = (Emprunt)em.find(Emprunt.class, emprunt.getIdEmprunt());
		emp.setAvisSurEmprunteur(emprunt.getAvisSurEmprunteur());
		
		em.merge(emprunt);
		return emprunt.getIdEmprunt();

	}

	@Override
	public List<Emprunt> getEmpruntsAnnules(Proprietaire prop) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.proprietaire.idUtilisateur = :pmp " + 
				   "AND e.dateAnnulation IS NOT NULL");

		hql.setParameter("pmp", prop.getIdUtilisateur());
		List<Emprunt> emps = (List<Emprunt>)hql.getResultList();
		
		return emps;

	}

	@Override
	public List<Emprunt> getEmpruntsRefuses(Proprietaire prop) {
		
		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.proprietaire.idUtilisateur = :pmp " + 
				   "AND e.dateRefus IS NOT NULL");

		hql.setParameter("pmp", prop.getIdUtilisateur());
		List<Emprunt> emps = (List<Emprunt>)hql.getResultList();
		
		return emps;

	}

	@Override
	public List<Emprunt> getPrets(Proprietaire prop) {
		
		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.aem.proprietaire.idUtilisateur = :pmp");

		hql.setParameter("pmp", prop.getIdUtilisateur());
		List<Emprunt> prets = hql.getResultList();
		
		return prets;
	}

	@Override
	public List<Emprunt> getPrets(Date debut, Date fin) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.dateDebut > :pmp1" + 
				   "AND (e.dateFin < :pmp2 OR e.dateRestitution < :pmp2)");
		
		hql.setParameter("pmp1", debut);
		hql.setParameter("pmp2", fin);
		List<Emprunt> prets = hql.getResultList();
		
		return prets;
	}

	@Override
	public List<Emprunt> getPretsPasses(Proprietaire prop) {
		
		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.aem.proprietaire.idUtilisateur=:pmp1 " + 
				   "AND e.dateValidation IS NOT NULL " + 
				   "AND e.dateRestitution < CURRENT_DATE " + 
				   "AND e.dateAnnulation IS NULL");
		
		hql.setParameter("pmp1", prop.getIdUtilisateur());
		List<Emprunt> prets = hql.getResultList();
		
		return prets;

	}

	@Override
	public List<Emprunt> getPretsEnCours(Proprietaire prop) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.aem.proprietaire.idUtilisateur = :pmp1 " + 
				   "AND e.dateValidation IS NOT NULL " + 
				   "AND e.dateDebut < CURRENT_DATE " + 
				   "AND e.dateRestitution IS NULL " + 
				   "AND e.dateAnnulation IS NULL");

		hql.setParameter("pmp1", prop.getIdUtilisateur());
		List<Emprunt> prets = hql.getResultList();
		
		return prets;

	}

	@Override
	public List<Emprunt> getPretsPlannifies(Proprietaire prop) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.aem.proprietaire.idUtilisateur = :pmp1 " + 
				   "AND e.dateValidation IS NOT NULL " + 
				   "AND e.dateDebut > CURRENT_DATE " + 
				   "AND e.dateAnnulation IS NULL");

		hql.setParameter("pmp1", prop.getIdUtilisateur());
		List<Emprunt> prets = hql.getResultList();
		
		return prets;

	}

	@Override
	public List<Emprunt> getPretsNonValides(Proprietaire prop) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.aem.proprietaire.idUtilisateur = :pmp " + 
				   "AND e.dateValidation IS NULL " + 
				   "AND e.dateRestitution IS NULL " + 
				   "AND e.dateAnnulation IS NULL");

		hql.setParameter("pmp", prop.getIdUtilisateur());
		List<Emprunt> pretsNonValides = hql.getResultList();
		
		return pretsNonValides;

	}

	@Override
	public List<Emprunt> getPretsAnnules(Proprietaire prop) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.aem.proprietaire.idUtilisateur = :pmp " + 
				   "AND e.dateAnnulation IS NOT NULL");

		hql.setParameter("pmp", prop.getIdUtilisateur());
		List<Emprunt> prets = hql.getResultList();
		
		return prets;

	}

	@Override
	public List<Emprunt> getPretsRefuses(Proprietaire prop) {

		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " + 
				   "WHERE e.aem.proprietaire.idUtilisateur = :pmp " + 
				   "AND e.dateRefus IS NOT NULL");

		hql.setParameter("pmp", prop.getIdUtilisateur());
		List<Emprunt> prets = hql.getResultList();
		
		return prets;

	}

	@Override
	public Emprunt getEmprunt(Avis a) {
		
		Query hql = em.createQuery("SELECT e FROM Emprunt e " + 
				   "LEFT JOIN FETCH e.avisSurEmprunteur " + 
				   "LEFT JOIN FETCH e.avisSurPreteur " + 
				   "INNER JOIN FETCH e.aem " + 
				   "INNER JOIN FETCH e.proprietaire " +
				   "LEFT JOIN FETCH e.motivationAnnulation " + 
				   "LEFT JOIN FETCH e.motivationRefus " +
				   "WHERE e.avisSurPreteur.idAvis = :pmp");

		hql.setParameter("pmp", a.getIdAvis());
		Emprunt emp = (Emprunt) hql.getSingleResult();

		return emp;

	}

}
